// 分段上传帮助类
import { generateSeriaNumber } from '@/utils/generateSeriaNumber';
import type { UploadFileParams } from '@/utils/http/axios';
import { resourcesResourcesApi } from '@/api/zyApi';
import { getPercentage } from '@/utils/util';
import {ref, type Ref } from "vue";

export interface ChunksUploadReturnType {
    /**
     * 上传
     * @param fileid 资源ID
     * @param useType 类型0=未知 2=图片 4=视频
     * @param options 选项
     * @constructor
     */
    Upload: (fileid: string, useType: number, options: ChunksUploadRequestOptions) => void;

    /**
     * 取消上传
     * @constructor
     */
    CancelUpload: () => void;
}
// 上传文件数据
export interface ChunksUploadFileData {
    // 当前已上传的进度
    uploadPercentage: number;
    // 是否上传成功
    isSuccess: boolean;
    // 文件名
    fileName: string;
}

export interface ChunksUploadFileReturnType {
    /**
     * 上传
     * @param fileid 资源ID
     * @param options 选项
     * @constructor
     */
    Upload: (fileid: string, options: ChunksUploadRequestOptions) => void;
    // 上传文件
    HandleFileUpload(file: File, successCallback: () => void): boolean;
    /**
     * 取消上传
     * @constructor
     */
    CancelUpload: () => void;

    // 上传文件数据
    UploadData: Ref<ChunksUploadFileData>;
}

type ChunksUploadCallback = (param: UploadFileParams) => Promise<any>;

export interface ChunksUploadProgressEvent {
    // 上传百分比
    percent: number;
}

export interface ChunksUploadRequestOptions {
    file: File;
    onError?: (evt: Error) => void;
    onProgress?: (evt: ChunksUploadProgressEvent) => void;
    onSuccess?: (response: any) => void;
}

/**
 * 使用分片上传
 */
export function useChunksUpload(): ChunksUploadReturnType {
    const getInstance = () => {
        let isUpload: boolean = false;
        return {
            CancelUpload() {
                isUpload = false;
            },
            Upload(fileid: string, useType: number, options: ChunksUploadRequestOptions) {
                isUpload = true;
                // 创建上传文件分片缓冲区
                let fileChunks: any[] = [];
                // 目标文件
                let file = options.file;
                // 设置分片缓冲区大小
                let maxFileSizeMB = 8;
                let bufferChunkSize = maxFileSizeMB * (1024 * 1024);
                // 读取文件流起始位置
                let fileStreamPos = 0;
                // 设置下一次读取缓冲区初始大小
                let endPos = bufferChunkSize;
                // 文件大小
                let size = file.size;
                // 将文件进行循环分片处理塞入分片数组
                while (fileStreamPos < size) {
                    let fileChunkInfo = {
                        file: file.slice(fileStreamPos, endPos),
                        start: fileStreamPos,
                        end: endPos,
                    };
                    fileChunks.push(fileChunkInfo);
                    fileStreamPos = endPos;
                    endPos = fileStreamPos + bufferChunkSize;
                }
                // 获取上传文件分片总数量
                let totalParts = fileChunks.length;
                let partCount = 0;
                const uploadFile = () => {
                    if (fileChunks.length <= 0) {
                        return;
                    }
                    if (!isUpload) {
                        return;
                    }
                    partCount++;
                    let chunk = fileChunks.shift();
                    resourcesResourcesApi
                        .ChunksUpload(fileid, String(useType), {
                            name: 'file',
                            file: chunk.file,
                            filename: file.name,
                            data: {
                                PartNumber: partCount,
                                Size: bufferChunkSize,
                                Chunks: totalParts,
                                Start: chunk.start,
                                End: chunk.end,
                                Total: size,
                            },
                        })
                        .then(() => {
                            if (partCount == totalParts) {
                                if (options.onProgress) {
                                    options.onProgress({
                                        percent: 100,
                                    });
                                }
                                if (options.onSuccess) {
                                    options.onSuccess({
                                        fileId: fileid,
                                        filename: file.name,
                                    });
                                }

                                return;
                            } else {
                                if (options.onProgress) {
                                    options.onProgress({
                                        percent: 100 - getPercentage(totalParts, partCount),
                                    });
                                }
                            }
                            uploadFile();
                        })
                        .catch((err) => {
                            if (options.onError) {
                                options.onError(err);
                            }
                        });
                };
                uploadFile();
            },
        };
    };
    return getInstance();
}

/**
 * 使用分片上传文件可指定方法
 */
export function useChunksUploadFile(callback: ChunksUploadCallback): ChunksUploadFileReturnType {
    const getInstance = () => {
        let isUpload: boolean = false;
        const uploadData = ref<ChunksUploadFileData>({
            uploadPercentage: 0,
            isSuccess: false,
            fileName: '',
        });
        const api = {
            UploadData: uploadData,

            CancelUpload() {
                isUpload = false;
            },
            HandleFileUpload(file: File, successCallback: () => void) {
                uploadData.value.fileName = file.name;
                const fid = `res-temp-${new Date().getTime()}${generateSeriaNumber()}`;
                console.log(file);
                api.Upload(fid, {
                    file: file,
                    onSuccess: () => {
                        console.log("上传成功");
                        successCallback();
                    },
                });
                return false;
            },
            Upload(fileid: string, options: ChunksUploadRequestOptions) {
                isUpload = true;
                // 创建上传文件分片缓冲区
                let fileChunks: any[] = [];
                // 目标文件
                let file = options.file;

                // 设置分片缓冲区大小
                let maxFileSizeMB = 8;
                let bufferChunkSize = maxFileSizeMB * (1024 * 1024);
                // 读取文件流起始位置
                let fileStreamPos = 0;
                // 设置下一次读取缓冲区初始大小
                let endPos = bufferChunkSize;
                // 文件大小
                let size = file.size;
                // 将文件进行循环分片处理塞入分片数组
                while (fileStreamPos < size) {
                    let fileChunkInfo = {
                        file: file.slice(fileStreamPos, endPos),
                        start: fileStreamPos,
                        end: endPos,
                    };
                    fileChunks.push(fileChunkInfo);
                    fileStreamPos = endPos;
                    endPos = fileStreamPos + bufferChunkSize;
                }
                // 获取上传文件分片总数量
                let totalParts = fileChunks.length;
                let partCount = 0;
                const uploadFile = () => {
                    if (fileChunks.length <= 0) {
                        return;
                    }
                    if (!isUpload) {
                        return;
                    }
                    partCount++;
                    let chunk = fileChunks.shift();
                    console.log(chunk);
                    callback({
                        name: 'file',
                        file: chunk.file,
                        filename: file.name,
                        data: {
                            PartNumber: partCount,
                            Size: bufferChunkSize,
                            Chunks: totalParts,
                            Start: chunk.start,
                            End: chunk.end,
                            Total: size,
                        },
                    })
                        .then(() => {
                            if (partCount == totalParts) {
                                if (options.onProgress) {
                                    options.onProgress({
                                        percent: 100,
                                    });
                                }
                                if (options.onSuccess) {
                                    options.onSuccess({
                                        fileId: fileid,
                                        filename: file.name,
                                    });
                                }
                                uploadData.value.isSuccess = true;
                                uploadData.value.uploadPercentage = 100;
                                return;
                            } else {
                                uploadData.value.uploadPercentage = 100 - getPercentage(totalParts, partCount);
                                if (options.onProgress) {
                                    options.onProgress({
                                        percent: 100 - getPercentage(totalParts, partCount),
                                    });
                                }
                            }
                            uploadFile();
                        })
                        .catch((err) => {
                            if (options.onError) {
                                options.onError(err);
                            }
                        });
                };
                uploadFile();
            },
        };
        return api;
    };
    return getInstance();
}
